﻿/*
This project and all of its code is/are Copyright (C) 2017  Nils Hunter Alving

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;

namespace DynamicTypeBuilder
{
    /// <summary>
    /// This class can be used to create or resolve a class from an interface definition
    /// </summary>
    public class TypeFactory
    {
        /// <summary>
        /// The name of the output assembly without the extension
        /// </summary>
        public const string OutputAssemblyName = "DynamicTypes";
        /// <summary>
        /// The name of the output assembly with the extension
        /// </summary>
        public const string OutputDLLName = "DynamicTypes.dll";

        static TypeFactory()
        {
            AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            Debug.WriteLine("Message");
            return Assembly.Load(args.Name);
        }

        /// <summary>
        /// Creates and loads an assembly with the given name that contains a type that implements all the interfaces in the list
        /// Note that only properties 
        /// </summary>
        /// <param name="assemblyName">The name of the assembly</param>
        /// <param name="interfaces">A list of interface types</param>
        public static void CreateDynamicAssembly(string assemblyName, List<Type> interfaces)
        {
            var assemName = new AssemblyName() { Name = assemblyName };
            var outputFilename = $"{assemblyName}.dll";
            var asemBuilder = Thread.GetDomain().DefineDynamicAssembly(assemName, AssemblyBuilderAccess.RunAndSave);
            var moduleBuilder = asemBuilder.DefineDynamicModule("DynamicModule", outputFilename);

            new TypeFactoryHelper(moduleBuilder).CreateTypesFromInterfacesInAssemblyModule(interfaces);
            asemBuilder.Save(outputFilename);       
        }
    }
}
